﻿using RimWorld;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Verse;
using Verse.AI;
using MVCF.Utilities;
using HarmonyLib;

namespace Miao.Stand
{
    /// <summary>
    /// 替身类
    /// </summary>
    abstract public class StandPawn : Pawn
    {
        public int LevelSpeed
        {
            set
            {
                standPower.levelSpeed = value;
            }
        }
        public float Consciousness;//意识
        #region 需要存储
        public Pawn owner;
        //public Pawn owner//使用自带的Master会需要使用动物的Training系统，会产生Tick开销（计算野性衰减），所以还是不用了
        //{
        //    get
        //    {
        //        return this.playerSettings.Master;
        //    }
        //    set
        //    {
        //        this.playerSettings.Master = value;
        //    }
        //}
        public bool ghostFollow;//替身是否像动画一样背后灵紧紧跟随
        #endregion

        public float standRanage;
        /// <summary>
        /// 持续性
        /// </summary>
        public float persistence;
        public float WanderRanage
        {
            get
            {
                return standRanage * 0.5f;
            }
        }
        virtual public void LevelSpeedChange()//是模型没渲染出来，明天看看
        {
            if(this.Spawned)
            {
                if (jobs?.curJob.def == StandJobDefOf.StandGhostFollow)//背后灵模式的恢复力很强
                {
                    LevelSpeed = 10;
                }
            }
            else
            {
                LevelSpeed = 10;
            }
        }

        virtual public float BeghaviorRanage//行为作战半径
        {
            get
            {
                if (Stand.Settings.StandRangeDistanceIsConsciousness)
                {
                    return standRanage * Consciousness;
                }
                return standRanage;
            }
        }
        virtual public float MaxRadius//最大移动范围半径，超出的情况下会被强制传送到主人旁
        {
            get
            {
                if (Stand.Settings.StandRangeDistanceIsConsciousness)
                {
                    return standRanage * 1.5f * Consciousness;
                }
                return standRanage * 1.5f;
            }
        }

        //总感觉这么写很生操
        public Need_StandPower standPower;
        public StandAbilityTracker standAbilityTracker;

        virtual public void InitStandAbility()
        {
            if(IsMeleeStand)
            {
                standAbilityTracker.standAbilities.Add(StandAbilityMaker.CreateStandAbility("OraOra", this));
            }
        }
        abstract public bool IsMeleeStand
        {
            get;
        }

        public virtual IEnumerable<Gizmo> GetDraftedStandGizmos()
        {
            return standAbilityTracker.GetGizmos();
        }
        

        public override void Tick()
        {
            base.Tick();
            if (!Suspended)
            {
                if (Spawned)
                {
                    standAbilityTracker.Tick();
                }
            }
        }

        public override void ExposeData()//此时父类def已经被读到了，所以可以被初始化应该
        {
            base.ExposeData();
            
            Scribe_References.Look<Pawn>(ref owner, "owner");
            Scribe_Values.Look<bool>(ref ghostFollow, "ghostFollow");
            Scribe_Deep.Look(ref standAbilityTracker, "standAbilityTracker", this);

            SetupField(def.GetModExtension<StandExtension>());//这个参数必须放外面，否则别人拿不到

            if (Scribe.mode==LoadSaveMode.ResolvingCrossRefs)
            {
                standPower = owner.needs.TryGetNeed<Need_StandPower>();
            }
        }
        public virtual void SetupField(StandExtension standExtension)
        {
            standRanage = standExtension.range;
            persistence = standExtension.persistence;
        }


        public override void Destroy(DestroyMode mode = DestroyMode.Vanish)
        {
            base.Destroy(mode);
        }

        #region Tick

        /// <summary>
        /// 稀有情况Tick
        /// </summary>
        public override void TickRare()
        {
            base.TickRare();

            if (this.Spawned)
            {
                if (this.owner.Dead)//如果人死了，则销毁替身
                {
                    if (Find.WorldPawns.Contains(this))
                    {
                        Find.WorldPawns.RemovePawn(this);
                    }
                    this.Destroy(DestroyMode.KillFinalize);
                    //this.DeSpawn(DestroyMode.KillFinalize);
                    return;
                }
                else if (this.owner.Downed)//主角躺了
                {
                    InactiveStand();
                    return;
                }
                else if (this.Map != this.owner.Map)//地图不同步也隐藏替身（只找到这个判断法）
                {
                    InactiveStand();
                    return;
                }

                ///在距离外
                if (!owner.Position.InHorDistOf(this.Position, MaxRadius))
                {
                    //Messages.Message("替身超距传回", MessageTypeDefOf.NeutralEvent);
                    jobs.StopAll();//干掉工作
                    pather.StopDead();//干掉寻路
                    ClearAllReservations(releaseDestinationsOnlyIfObsolete: false);//干掉预定
                                                                                   //this.SetPositionDirect(owner.Position.RandomAdjacentCell8Way());
                    this.Position = owner.Position.RandomAdjacentCell8Way();
                    Job waitjob = JobMaker.MakeJob(JobDefOf.Wait);//执行一步等待就可以有效防止传送失灵问题了
                    waitjob.expiryInterval = 20;
                    this.jobs.StartJob(waitjob);

                }
            }
        }
        #endregion

        public void ActiveStand(IntVec3 position, Map map)
        {
            position = position.RandomAdjacentCell8Way();//直接用这个就近创建替身

            GenSpawn.Spawn(this, position, map);
            //RCellFinder.RandomWanderDestFor(stand.owner, stand.owner.Position, stand.radius, null, Danger.None);
            //Thing data =  GenSpawn.Spawn(stand, position, map);
        }
        public void InactiveStand()
        {
            this.DeSpawn(DestroyMode.Vanish);
        }


        /// <summary>
        /// 预备添加伤害
        /// </summary>
        /// <param name="dinfo"></param>
        /// <param name="absorbed"></param>
        public override void PreApplyDamage(ref DamageInfo dinfo, out bool absorbed)
        {
            var standDamge = SetInjuryInMaster(dinfo);
            dinfo.Def.Worker.Apply(standDamge, owner);//添加伤害到本体
            dinfo.SetAmount(0);//设置到替身的伤害为0
            base.PreApplyDamage(ref dinfo, out absorbed);

        }
        /// <summary>
        /// 这段抄的是DamageWorker_AddInjury，但计算护甲拿的是替身计算。
        /// 然后计算完毕将伤害改为穿透护甲给我方单位
        /// </summary>
        /// <param name="dinfo"></param>
        protected DamageInfo SetInjuryInMaster(DamageInfo dinfo)
        {
            //DamageWorker.DamageResult damageResult = new DamageWorker.DamageResult();

            BodyPartRecord bodyPartRecord = owner.health.hediffSet.GetRandomNotMissingPart(dinfo.Def, dinfo.Height, dinfo.Depth);//随机拿个部位
            dinfo.SetHitPart(bodyPartRecord);
            bool deflectedByMetalArmor = false;
            float amount = dinfo.Amount;
            if (!dinfo.InstantPermanentInjury && !dinfo.IgnoreArmor)
            {
                DamageDef damageDef = dinfo.Def;
                amount = ArmorUtility.GetPostArmorDamage(this, amount, dinfo.ArmorPenetrationInt, dinfo.HitPart, ref damageDef, out deflectedByMetalArmor, out var diminishedByMetalArmor);
                dinfo.Def = damageDef;
                dinfo.SetAmount(amount);
            }
            dinfo.SetIgnoreArmor(true);
            return dinfo;
        }
        /// <summary>
        /// 广播伤害
        /// </summary>
        /// <param name="dinfo"></param>
        /// <param name="totalDamageDealt"></param>
        public override void PostApplyDamage(DamageInfo dinfo, float totalDamageDealt)
        {
            base.PostApplyDamage(dinfo, totalDamageDealt);

        }



        //画Gizmos
        public override IEnumerable<Gizmo> GetGizmos()
        {
            var Gizmos = base.GetGizmos();
            Gizmo drawCarry = DrawCarryGizmo();
            if (drawCarry != null)
            {
                Gizmos = Gizmos.AddItem(DrawCarryGizmo());
            }

            return Gizmos;
        }

        public Gizmo DrawCarryGizmo()
        {
            if (this.carryTracker.CarriedThing != null)
            {
                Command_Action command_Action = new Command_Action();
                command_Action.defaultLabel = "CommandDropPawn".Translate(this.carryTracker.CarriedThing);
                command_Action.defaultDesc = "CommandDropPawnDesc".Translate();
                command_Action.action = delegate
                {
                    this.carryTracker.TryDropCarriedThing(this.Position, ThingPlaceMode.Near, out var _);
                };
                command_Action.icon = TexCommand.DropCarriedPawn;
                return command_Action;
            }
            return null;
        }

        public bool HasBeghavior(Thing thingTarget)
        {
            ///是否在行动范围内
            if (owner.Position.InHorDistOf(thingTarget.Position, BeghaviorRanage))
            {
                return true;
            }
            else
            {
                Messages.Message("超出行动范围", MessageTypeDefOf.CautionInput);
                return false;
            }
        }
        public bool HasRangeAttack(Thing thingTarget)
        {

            foreach (var rangedVerb in this.Manager().CurrentlyUseableRangedVerbs)
            {
                if (this.Position.InHorDistOf(thingTarget.Position, rangedVerb.Verb.verbProps.range))
                {
                    return true;
                }
            }
            return false;
        }

        #region Functions
        /// <summary>
        /// 以own为基准绘制半径环
        /// </summary>
        /// <param name="center"></param>
        public void DrawBehaviorRadiusRing()
        {
            GenDraw.DrawRadiusRing(owner.Position, BeghaviorRanage);
        }
        /// <summary>
        /// 绘画替身的远程攻击
        /// </summary>
        public void DrawRangeRadiusRing()
        {
           

            foreach (var rangedVerb in this.Manager().CurrentlyUseableRangedVerbs)
            {
                GenDraw.DrawRadiusRing(Position, rangedVerb.Verb.verbProps.range, UnityEngine.Color.red);
            }
        }


        #endregion
    }
}
